﻿namespace GreenIsomer.Data.Entities.Transform {
	using System;
	using System.Xml;
	using System.Xml.Serialization;
	using System.IO;

	[Serializable, XmlType("EdmxInput", Namespace = Settings.Namespace)]
	public class EdmxInput : Input {

		private const string ssdlNamespace = "http://schemas.microsoft.com/ado/2006/04/edm/ssdl";
		private const string csdlNamespace = "http://schemas.microsoft.com/ado/2006/04/edm";
		private const string mslNamespace = "urn:schemas-microsoft-com:windows:storage:mapping:CS";

		[NonSerialized]
		private XmlDocument document;

		[NonSerialized]
		private XmlNamespaceManager namespaceManager;

		[NonSerialized]
		private XmlNode ssdlNode;

		[NonSerialized]
		private XmlNode csdlNode;

		[NonSerialized]
		private XmlNode mslNode;
		
		public EdmxInput() { }

		public override string DefaultFileExtension {
			get { return "edmx"; }
		}

		public override string TypeDescription {
			get { return "ADO.NET Entity Data Model"; }
		}

		public override string TypeName {
			get { return "EDMX"; }
		}

		public XmlDocument Document {
			get { return document; }
		}

		public XmlNode SsdlNode {
			get {
				if(ssdlNode == null) {
					if(document == null) throw new InvalidOperationException("Document not open.");
					ssdlNode = document.SelectSingleNode("//ssdl:Schema", namespaceManager);
					if(ssdlNode == null) throw new InvalidOperationException("SSDL information not found.");
				}
				return ssdlNode;
			}
		}

		public XmlNode CsdlNode {
			get {
				if(csdlNode == null) {
					if(document == null) throw new InvalidOperationException("Document not open.");
					csdlNode = document.SelectSingleNode("//csdl:Schema", namespaceManager);
					if(csdlNode == null) throw new InvalidOperationException("CSDL information not found.");
				}
				return csdlNode;
			}
		}

		public XmlNode MslNode {
			get {
				if(mslNode == null) {
					if(document == null) throw new InvalidOperationException("Document not open.");
					mslNode = document.SelectSingleNode("//msl:Mapping", namespaceManager);
					if(mslNode == null) throw new InvalidOperationException("MSL information not found.");
				}
				return mslNode;
			}
		}

		public override void Load(string baseDirectory) {
			try {

				document = new XmlDocument();

				using(TextReader reader = new StreamReader(Converter.ResolvePath(baseDirectory, File)))
					document.Load(reader);

				namespaceManager = new XmlNamespaceManager(document.NameTable);
				namespaceManager.AddNamespace("ssdl", ssdlNamespace);
				namespaceManager.AddNamespace("csdl", csdlNamespace);
				namespaceManager.AddNamespace("msl", mslNamespace);

			} catch(Exception) {
				document = null;
				namespaceManager = null;
				throw;
			}
		}

		public XmlNodeList GetSsdlEntitySetNodes() {
			return GetSsdlEntitySetNodes(SsdlNode);
		}
		public XmlNodeList GetSsdlEntitySetNodes(XmlNode clonedSsdlNode) {
			return clonedSsdlNode.SelectNodes("//ssdl:EntitySet", namespaceManager);
		}

		public XmlNodeList GetSsdlPropertyNodes() {
			return GetSsdlPropertyNodes(SsdlNode);
		}
		public XmlNodeList GetSsdlPropertyNodes(XmlNode clonedSsdlNode) {
			return clonedSsdlNode.SelectNodes("//ssdl:Property", namespaceManager);
		}
	}

}